/********************************************************/
/*	Copyright (C) 2016 Gong Li Bin		 	*/
/*	Project:	GoLib-1.0.0			*/
/*	Author:		gong_libin			*/
/*	Date:		2016_01_01			*/
/*	File:		GoPri.go			*/
/********************************************************/

package GoPro

import (
	"unsafe"
	. "GoGlb"
)

func __PriArrayCopy(d, s []byte) {
	for i, v := range s {
		d[i] = v; i ++
	}
}

func __PriInt162Arr(n int16) []byte {
	var r []byte
	r = make([]byte, unsafe.Sizeof(n))
	r[0] = byte((uint16(n) & 0xff00) >> 8)
	r[1] = byte(uint16(n) & 0x00ff)
	return r
}

func __PriInt322Arr(n int32) []byte {
	var r []byte
	r = make([]byte, unsafe.Sizeof(n))
	r[0] = byte((uint32(n) & 0xff000000) >> 24)
	r[1] = byte((uint32(n) & 0x00ff0000) >> 16)
	r[2] = byte((uint32(n) & 0x0000ff00) >> 8)
	r[3] = byte((uint32(n) & 0x000000ff))
	return r
}

func __PriArr2Int16(b []byte) int16 {
	return int16((b[0] << 8) | b[1])
}

func __PriArr2Int32(b []byte) int32 {
	return int32((b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3])
}

const (
	GO_PR_0		byte = 0x00
	GO_PR_1		byte = 0x01

	GO_PR_N		byte = 0x00
	GO_PR_Y		byte = 0x01

	GO_PR_SUCC	byte = 0x00
	GO_PR_FAIL	byte = 0x01

	GO_PR_CTRL	byte = 0x00
	GO_PR_DATA	byte = 0x01
	GO_PR_EXPA	byte = 0x04
	GO_PR_HEAD	byte = 0x0c
	GO_PR_FLAG	byte = 0xe8
)

/* pro */
type GoPri struct {
	Flag	byte
	Vers	byte
	Prot	byte
	Wide	byte
	Resp	byte
	Expa	byte
	Type	byte
	Verb	byte
	Attr	byte
	Rest	byte
	Totl	int16
	Leng	int32
	ExHd	[]byte
	Body	[]byte
}

func (p *GoPri) GoPriReset() {
	p.Flag = 0
	p.Vers = 0
	p.Prot = 0
	p.Wide = 0
	p.Resp = 0
	p.Expa = 0
	p.Type = 0
	p.Verb = 0
	p.Attr = 0
	p.Rest = 0
	p.Totl = 0
	p.Leng = 0
	p.ExHd = nil
	p.Body = nil
}

func (p *GoPri) GoPriDisplay() {
	GoPrint("Flag: 0x%02x\t", p.Flag);
	GoPrint("Vers: 0x%02x\t", p.Vers);
	GoPrint("Prot: 0x%02x\t", p.Prot);
	GoPrint("Wide: 0x%02x\t", p.Wide);
	GoPrint("Resp: 0x%02x\t", p.Resp);
	GoPrint("Expa: 0x%02x\n", p.Expa);
	GoPrint("Type: 0x%02x\t", p.Type);
	GoPrint("Verb: 0x%02x\t", p.Verb);
	GoPrint("Attr: 0x%02x\t", p.Attr);
	GoPrint("Rest: 0x%02x\t", p.Rest);
	GoPrint("Totl: %06d\t", p.Totl);
	GoPrint("Leng: %08d\n", p.Leng);
}

func (p *GoPri) GoPriCreate() ([]byte, int) {
	i := 0
	b := make([]byte, GO_KBYTES2)
	b[i] = p.Flag; i ++
	b[i] = p.Vers << 4
	b[i] |= p.Prot << 3
	b[i] |= p.Wide << 2
	b[i] |= p.Resp << 1
	b[i] |= p.Expa; i ++
	b[i] = p.Type; i ++
	b[i] = p.Verb; i ++
	b[i] = p.Attr; i ++
	b[i] = p.Rest; i ++
	t := __PriInt162Arr(p.Totl)
	b[i] = t[0]; i++; b[i] = t[1]; i ++
	l := __PriInt322Arr(p.Leng)
	b[i] = l[0]; i++; b[i] = l[1]; i ++; b[i] = l[2]; i++; b[i] = l[3]; i ++
	if GO_PR_Y == p.Expa {
		for _, v := range p.ExHd {
			b[i] = v
			i += 1
		}
	}
	for n := 0; n < int(p.Leng); n ++ {
		b[i] = p.Body[n]
		i += 1
	}
	return b, i
}

func (p *GoPri) GoPriParse(b []byte) int {
	i := 0
	p.Flag = b[i]; i ++
	p.Vers = b[i] >> 4
	p.Prot = (b[i] & 0x0f) >> 3
	p.Wide = (b[i] & 0x07) >> 2
	p.Resp = (b[i] & 0x03) >> 1
	p.Expa = b[i] & 0x01; i++
	p.Type = b[i]; i++
	p.Verb = b[i]; i++
	p.Attr = b[i]; i++
	p.Rest = b[i]; i++
	p.Totl = __PriArr2Int16(b[i : i + 2]); i += int(unsafe.Sizeof(p.Totl))
	p.Leng = __PriArr2Int32(b[i : i + 4]); i += int(unsafe.Sizeof(p.Leng))
	if GO_PR_Y == p.Expa {
		p.ExHd = b[i : 4]; i += int(GO_PR_EXPA)
	}
	if i < len(b) {
		p.Body = b[i : ]
	}
	return i
}

/* k&v */
func GoKvDisplay(k interface{}) {
	switch k.(type) {
		case GoKlv:
			GoPrint("Key[0x%02x] -> Lng[0x%02x] -> Val[%s]\n", (k.(GoKlv)).Key, (k.(GoKlv)).Lng, (k.(GoKlv)).Val);
		case GoWkv:
			GoPrint("WKy[0x%02x] -> Lng[0x%02x] -> Val[%s]\n", (k.(GoWkv)).Key, (k.(GoWkv)).Lng, (k.(GoWkv)).Val);
		default:
	}
}

/* klv */
type GoKlv struct {
	Key	byte
	Lng	int32
	Val	[]byte
}

func GoKlvDisplay(k []GoKlv) {
	for _, v := range k {
		GoKvDisplay(v)
	}
}

func GoKlvInit(t int16) []GoKlv {
	return make([]GoKlv, t)
}

func GoKlvInput(b []byte, k []GoKlv) {
	i := int32(0)
	j := int32(unsafe.Sizeof(k[0].Lng))
	for n := 0; n < len(k); n ++ {
		k[n].Key = b[i]; i ++
		k[n].Lng = __PriArr2Int32(b[i : i + j])
		i += j; k[n].Val = b[i : i + k[n].Lng]; i += k[n].Lng
	}
}

func GoKlvOutput(b []byte, k []GoKlv) int32 {
	i := int32(0)
	l := int32(unsafe.Sizeof(k[0].Lng))
	for n := 0; n < len(k); n ++ {
		b[i] = k[n].Key; i ++
		__PriArrayCopy(b[i : ], __PriInt322Arr(k[n].Lng)); i += l
		__PriArrayCopy(b[i : ], k[n].Val); i += int32(len(k[n].Val))
	}
	return i
}

/* wkv */
type GoWkv struct {
	Key	int16
	Lng	int32
	Val	[]byte
}

func GoWkvDisplay(k []GoWkv) {
	for _, v := range k {
		GoKvDisplay(v)
	}
}

func GoWkvInit(t int16) []GoWkv {
	return make([]GoWkv, t)
}

func GoWkvInput(b []byte, k []GoWkv) {
	i := int32(0)
	l16 := int32(unsafe.Sizeof(k[0].Key))
	l32 := int32(unsafe.Sizeof(k[0].Lng))
	for n := 0; n < len(k); n ++ {
		k[n].Key = __PriArr2Int16(b[i : i + l16]); i += l16
		k[n].Lng = __PriArr2Int32(b[i : i + l32]); i += l32
		k[n].Val = b[i : k[n].Lng]; i += k[n].Lng
	}
}

func GoWkvOutput(b []byte, k []GoWkv) int32 {
	i := int32(0)
	l16 := int32(unsafe.Sizeof(k[0].Key))
	l32 := int32(unsafe.Sizeof(k[0].Lng))
	for n := 0; n < len(k); n ++ {
		__PriArrayCopy(b[i : ], __PriInt162Arr(k[n].Key)); i += l16
		__PriArrayCopy(b[i : ], __PriInt322Arr(k[n].Lng)); i += l32
		__PriArrayCopy(b[i : ], k[n].Val); i += int32(len(k[n].Val))
	}
	return i
}
